package com.handpay.framework.swiper;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Hashtable;
import java.util.Locale;
import java.util.concurrent.TimeoutException;

import android.content.Context;
import android.text.TextUtils;

import com.bbpos.emvswipe.EmvSwipeController;
import com.bbpos.emvswipe.EmvSwipeController.CheckCardMode;
import com.handpay.framework.swiper.ic.IICSelectApplicationCallback;
import com.handpay.framework.swiper.ic.IShowSelectApplication;
import com.handpay.zztong.hp.R;
import com.handpay.zztong.hp.config.ZZTConstant;
import com.handpay.zztong.hp.log.HPLog;

/**
 * Created by jmshuai on 2014/8/12.
 */
class BbposVoiceSwiper extends AbstractBbposSwiper implements
		EmvSwipeController.EmvSwipeControllerListener {
	protected EmvSwipeController mEmvSwipeController;
	protected IShowSelectApplication mSelectApplication;
	private static final String TAG = BbposVoiceSwiper.class.getSimpleName();
	private String mData;
	EmvSwipeController.CheckCardResult mCheckCardResult;
	private Context mContext;
	private SwipeTransData mSwipeTransData;
	protected static String apdus[] = { "801a1301082012101111245180",
			"80fa000018363232383738303231323231393330373030000000000000", };
	private volatile boolean mIsSwiperOK = true;

	public BbposVoiceSwiper(Context c, IShowSelectApplication selectApplication) {
		mContext = c;
		mEmvSwipeController = new EmvSwipeController(c, this);
		mEmvSwipeController.startAudio();
		mLock = new AsynSwiperLock();
		mSelectApplication = selectApplication;
		mIsSwiperOK = true;
	}

	@Override
	public String getCSN() {
		mData = null;
		mEmvSwipeController.getKsn();
		try {
			mLock.lock(ZZTConstant.SWIPER_TIMEOUT, AsynSwiperLock.GETCSN);
		} catch (TimeoutException te) {
			HPLog.i(TAG, "", te);
		}
		return mData == null ? null : mData.toUpperCase(Locale.US);
	}

	@Override
	public boolean stopOperation() {
		// if (mLock.getCurrrentCmdType() == AsynSwiperLock.NEW_SWIPE_CARD) {
		// 从文峻那里得知cancelCheckCard貌似是作用比较多
		mEmvSwipeController.cancelCheckCard();
		// }
		return true;
	}

	@Override
	public boolean closeDevice() {
		HPLog.i(TAG, "close");
		mSelectApplication = null;
		mContext = null;
		mSwipeTransData = null;
		mIsSwiperOK = false;
		if (mEmvSwipeController != null) {
			mEmvSwipeController.stopAudio();
			mEmvSwipeController.resetEmvSwipeController();
			mEmvSwipeController = null;
		}
		return true;
	}

	private void initTransData(String factor, int timeOut) {
		// mHTData，可以在后面完全被SwipeTransData取代
		mHTData.clear();
		mSwipeTransData = new SwipeTransData();
		mSwipeTransData.mBbposICTranIndex = 0;
		mSwipeTransData.mFactor = factor;
		mSwipeTransData.mTimeout = timeOut;
	}

	public SwipeResult iccStartEmv() {
		int timeout = mSwipeTransData.mTimeout;
		String factor = mSwipeTransData.mFactor;
		String strTimeOut = "" + timeout;
		// 2.7.2新增 和修改
		Hashtable<String, Object> data = new Hashtable<String, Object>();
		// Hashtable<String, String> data = new Hashtable<String, String>();
		String userTime = new SimpleDateFormat("yyMMddHHmmss").format(Calendar
				.getInstance().getTime());
		data.put("terminalTime", userTime);
		data.put("checkCardTimeout", strTimeOut);
		data.put("setAmountTimeout", strTimeOut);
		data.put("selectApplicationTimeout", strTimeOut);
		data.put("finalConfirmTimeout", strTimeOut);
		data.put("onlineProcessTimeout", strTimeOut);
		data.put("randomNumber", factor);
		// 新增2.7.2
		data.put("pinEntryTimeout", strTimeOut);
		data.put("emvOption", "START");
		data.put("checkCardMode", CheckCardMode.SWIPE_OR_INSERT);

		mData = null;
		mEmvSwipeController.startEmv(data);
		HPLog.i(TAG, "iccStartEmv:  读取ICC的信息");
		try {
			// 暂时用OLD_INPUT_PWD来锁住IC startEmv
			mLock.lock(timeout * 5, AsynSwiperLock.OLD_INPUT_PWD);
		} catch (TimeoutException te) {
			HPLog.e(TAG, "", te);
		}
		if (null != mSelectApplication) {
			mSelectApplication.closeSelectICApp();
		}
		HPLog.i(TAG, "iccStartEmv:ICC的信息返回");
		String tlv = mData;
		mData = null;
		if (TextUtils.isEmpty(tlv)) {
			return new SwipeResult(SwipeStatus.SWIPE_ERROR);
		}
		Hashtable<String, String> decodeData = EmvSwipeController
				.decodeTlv(tlv);
		Object[] keys = decodeData.keySet().toArray();
		String content = "";
		for (Object key : keys) {
			String value = decodeData.get(key);
			content += key + ": " + value + "\n";
		}
		HPLog.e(TAG, content);
		String PAN = decodeData.get("maskedPAN");
		if (!TextUtils.isEmpty(PAN)) {
			mHTData.put(IBusinessSwiper.BANK_PLAIN_ACCOUNT_KEY,
					PAN.toUpperCase(Locale.US));
		} else {
			HPLog.i(TAG, "IC card but no PAN");
		}
		String track2 = decodeData.get("encTrack2Eq");
		if (!TextUtils.isEmpty(track2)) {
			mHTData.put(IBusinessSwiper.BANK_TRACK2_KEY, BusinessSwiper
					.autoFillTrack2(track2.toUpperCase(Locale.US)));
		} else {
			HPLog.i(TAG, "IC card but no BANK_TRACK2");
		}
		// mAccount = decodeData.get("maskedPAN");
		// mAccount = mAccount.replace("f", "");
		String tKey = decodeData.get("encTrack2EqRandomNumber");
		if (!TextUtils.isEmpty(tKey)) {
			mHTData.put(IBusinessSwiper.BANK_DYNAMIC_KEY,
					tKey.toUpperCase(Locale.US));
		} else {
			HPLog.i(TAG, "IC card but no BANK_DYNAMIC");
		}

		// 2.0.0 添加ＩＣ卡有效期
		String plainExpireDate = decodeData.get("5F24");
		HPLog.i(TAG, "BbposVoiceSwiper  -- plainExpireDate:" + plainExpireDate);
		if (!TextUtils.isEmpty(plainExpireDate)) {
			plainExpireDate = plainExpireDate.substring(0, 4);
			mHTData.put(IBusinessSwiper.BANK_PLAIN_EXPIRE_DATE, plainExpireDate);
		} else {
			HPLog.i(TAG, "IC card but no plainExpireDate");
		}

		// 2.7.2修改
		String icNumber = decodeData.get("5F34");
		// String icNumber = decodeData.get("5f34");
		if (!TextUtils.isEmpty(icNumber)) {
			icNumber = "0" + icNumber;
			mHTData.put(IBusinessSwiper.BANK_ICNUMBER, icNumber);
		} else {
			HPLog.i(TAG, "IC card but no icNumber");
		}
		String mdcData = EmvSwipeController.viposGetIccData(tlv);
		if (!TextUtils.isEmpty(mdcData)) {
			mHTData.put(IBusinessSwiper.BANK_DCDATA,
					mdcData.toUpperCase(Locale.US));
		} else {
			HPLog.e(TAG, "IC card but no dcData");
			return new SwipeResult(SwipeStatus.SWIPE_ERROR);
		}
		return new SwipeResult(SwipeStatus.SWIPE_OK, PAN);
	}

	@Override
	public SwipeResult swipeCard(String factor, int timeout) {
		HPLog.i(TAG, "swipeCard:等待刷卡。。。。");
		Hashtable<String, Object> data = new Hashtable<String, Object>();
		String strTimeOut = "" + timeout;
		data.put("checkCardTimeout", strTimeOut);
		data.put("randomNumber", factor);
		// 每次刷卡的时候，清除所有数据
		// 2.7.2添加
		data.put("checkCardMode", CheckCardMode.SWIPE_OR_INSERT);
		initTransData(factor, timeout);
		mCheckCardResult = EmvSwipeController.CheckCardResult.NONE;
		mEmvSwipeController.checkCard(data);
		try {
			mLock.lock(timeout, AsynSwiperLock.NEW_SWIPE_CARD);
		} catch (TimeoutException te) {
			HPLog.i(TAG, "", te);
			return new SwipeResult(SwipeStatus.SWIPE_TIMEOUT);
		}
		HPLog.i(TAG, "swipeCard:解锁。。。");
		if (EmvSwipeController.CheckCardResult.MCR == mCheckCardResult) {
			// 磁条卡
			// 检查磁条刷卡所必备的数据
			if (null == mHTData.get(IBusinessSwiper.BANK_DYNAMIC_KEY)) {
				HPLog.e(TAG, "no dynamic key");
				return new SwipeResult(SwipeStatus.SWIPE_ERROR);
			}
			if (null == mHTData.get(IBusinessSwiper.BANK_TRACK2_KEY)) {
				HPLog.e(TAG, "no track2");
				return new SwipeResult(SwipeStatus.SWIPE_ERROR);
			}
			if (null == mHTData.get(IBusinessSwiper.BANK_PLAIN_ACCOUNT_KEY)) {
				HPLog.e(TAG, "no plain account");
				return new SwipeResult(SwipeStatus.SWIPE_ERROR);
			}
			SwipeResult result = new SwipeResult(SwipeStatus.SWIPE_OK,
					mHTData.get(IBusinessSwiper.BANK_PLAIN_ACCOUNT_KEY));
			result.mCardType = mHTData.get("cardType");
			return result;
		} else if (EmvSwipeController.CheckCardResult.ICC == mCheckCardResult) {
			// IC卡
			mSwipeTransData.isIcTrans = true;
			mData = null;
			mEmvSwipeController.getEmvCardNumber();
			try {
				// 暂时用OLD_SWIPE_CARD来锁住IC的获取卡号
				mLock.lock(ZZTConstant.SWIPER_TIMEOUT,
						AsynSwiperLock.OLD_SWIPE_CARD);
			} catch (TimeoutException te) {
				HPLog.i(TAG, "", te);
				return new SwipeResult(SwipeStatus.SWIPE_TIMEOUT);
			}
			if (TextUtils.isEmpty(mData)) {
				return new SwipeResult(SwipeStatus.SWIPE_ERROR);
			}
			mHTData.put(IBusinessSwiper.BANK_PLAIN_ACCOUNT_KEY, mData);
			return new SwipeResult(SwipeStatus.SWIPE_OK, mData);
		} else if (null == mCheckCardResult) {
			HPLog.i(TAG, "bbpos cancel card");
			// 当取消处理
			return new SwipeResult(SwipeStatus.SWIPE_CANCEL);
		} else {
			// 当做错误处理
			return new SwipeResult(SwipeStatus.SWIPE_ERROR);
		}
	}

	@Override
	public String encData(String data, String index, String factor) {
		HPLog.i(TAG, "data:" + data + " index:" + index + " factor:" + factor);
		mData = null;
		String time = factor.substring(0, factor.length() - 2);
		Hashtable<Integer, String[]> example = new Hashtable<Integer, String[]>();
		try {
			if (ISwiperListener.MacDataIndex.equals(index)) {
				char[] mac = data.toCharArray();
				ByteArrayOutputStream bos = new ByteArrayOutputStream();
				try {
					bos.write(new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
							0x00, 0x00 });
					bos.write(String.valueOf(mac).getBytes());
					bos.write(0x80);
					while (bos.size() % 8 != 0) {
						bos.write(0x00);
					}
					byte[] dataBytes = bos.toByteArray();
					bos.close();
					for (String partMac : formatMacString(dataBytes)) {
						Hashtable<Integer, String[]> hashtable = new Hashtable<Integer, String[]>(
								1);
						hashtable.put(SINGLE_ENC_MAC_KEY, new String[] { "15",
								time, partMac });
						mData = null;
						mEmvSwipeController.viposBatchExchangeApdu(hashtable);
						mLock.lock(ZZTConstant.SWIPER_TIMEOUT,
								AsynSwiperLock.CACL_MAC);
						HPLog.i(TAG, partMac + " macResult: " + mData);
						if (null != mData && mData.endsWith("9000")) {
							// 成功。去掉9000。中间返回是9000，mData就是“”，最后的话，mData就是算出来的mac
							mData = mData.substring(0, mData.length() - 4)
									.toUpperCase();
						} else {
							// 失败了。设置mac加密失败。并退出循环
							mData = null;
							break;
						}
					}
				} catch (IOException ioe) {
					HPLog.e(TAG, "", ioe);
				}
			} else if (ISwiperListener.KeyDataIndex.equals(index)) {
				String cmd = formatDataAdpu(data);
				HPLog.i(TAG, "13 cmd:" + cmd);
				example.put(SINGLE_ENC_DATA_KEY,
						new String[] { "13", time, cmd });
				mEmvSwipeController.viposBatchExchangeApdu(example);
				mLock.lock(ZZTConstant.SWIPER_TIMEOUT, AsynSwiperLock.CACL_DATA);
			} else if (PIN_INDEX.equals(index)) {
				example.put(SINGLE_ENC_DATA_KEY, new String[] { "14", time,
						"80fa00000806" + data + "ffffffff" });
				mEmvSwipeController.viposBatchExchangeApdu(example);
				mLock.lock(ZZTConstant.SWIPER_TIMEOUT, AsynSwiperLock.CACL_DATA);
			}
		} catch (TimeoutException te) {
			HPLog.i(TAG, "", te);
		}
		return mData;
	}

	@Override
	public boolean isSwiperReady() {
		return mIsSwiperOK;
	}

	@Override
	public SwiperModel getSwiperModel() {
		return SwiperModel.BBPOS_VOICE;
	}

	@Override
	// public void onWaitingForCard() {
	// 2.7.2新增修改接口
	public void onWaitingForCard(CheckCardMode arg0) {
		HPLog.i(TAG, "onWaitingForCard:");
	}

	@Override
	public void onReturnCheckCardResult(
			EmvSwipeController.CheckCardResult checkCardResult,
			Hashtable<String, String> decodeData) {
		HPLog.i(TAG, "onReturnCheckCardResult:" + checkCardResult);
		mCheckCardResult = checkCardResult;
		if (checkCardResult == EmvSwipeController.CheckCardResult.ICC) {
			HPLog.e(TAG, "startEmv");
		} else if (checkCardResult == EmvSwipeController.CheckCardResult.MCR) {
			// String formatID = decodeData.get("formatID");
			// String maskedPAN = decodeData.get("maskedPAN");
			String PAN = decodeData.get("PAN");
			
			String expiryDate = decodeData.get("expiryDate");
			mHTData.put(IBusinessSwiper.BANK_PLAIN_EXPIRE_DATE, expiryDate);

			
			// String expiryDate = decodeData.get("expiryDate");
			// String cardHolderName = decodeData.get("cardholderName");
			// String ksn = decodeData.get("ksn");
			// String track1Length = decodeData.get("track1Length");
			// String track2Length = decodeData.get("track2Length");
			// String track3Length = decodeData.get("track3Length");
			// String encTracks = decodeData.get("encTracks");
			// String encTrack1 = decodeData.get("encTrack1");
			String encTrack2 = decodeData.get("encTrack2");
			HPLog.e(TAG, "bbpos-encTrack2--:" + encTrack2);
			String dynamicKeyData = decodeData.get("randomNumber");
			mHTData.put(IBusinessSwiper.BANK_DYNAMIC_KEY,
					dynamicKeyData.toUpperCase(Locale.US));
			mHTData.put(IBusinessSwiper.BANK_TRACK2_KEY, BusinessSwiper
					.autoFillTrack2(encTrack2.toUpperCase(Locale.US)));
			mHTData.put(IBusinessSwiper.BANK_PLAIN_ACCOUNT_KEY, PAN);
			String serviceCode = decodeData.get("serviceCode");
			if(serviceCode!=null&&serviceCode.length()>0){
				String cardType = serviceCode.substring(0, 1);
				if (!TextUtils.isEmpty(cardType)) {
					mHTData.put("cardType", cardType);
				}
			}
			if (TextUtils.isEmpty(PAN) || TextUtils.isEmpty(dynamicKeyData)
					|| TextUtils.isEmpty(encTrack2)) {
				HPLog.e(TAG,
						"PAN or dynamicKeyData or encTrack2 empty! notify re-swipe");
				mCheckCardResult = EmvSwipeController.CheckCardResult.NONE;
			}
			// String encTrack3 = decodeData.get("encTrack3");
			// String partialTrack = decodeData.get("partialTrack");
			// String trackEncoding = decodeData.get("trackEncoding");
			// String finalMessage = decodeData.get("finalMessage");
		}
		mLock.unlock(AsynSwiperLock.NEW_SWIPE_CARD);
	}

	@Override
	public void onReturnCancelCheckCardResult(boolean b) {
		HPLog.i(TAG, "onReturnCancelCheckCardResult:" + b);
		mCheckCardResult = null;
		mLock.unlock(AsynSwiperLock.NEW_SWIPE_CARD);
	}

	@Override
	public void onReturnEncryptPinResult(String s, String s2) {
		HPLog.i(TAG, "onReturnEncryptPinResult: " + s + " " + s2);
	}

	@Override
	public void onReturnEncryptDataResult(String s, String s2) {
		HPLog.i(TAG, "onReturnEncryptDataResult: " + s + " " + s2);
	}

	@Override
	public void onReturnStartEmvResult(
			EmvSwipeController.StartEmvResult startEmvResult, String s) {
		HPLog.i(TAG, "onReturnStartEmvResult:" + startEmvResult + " " + s);
	}

	@Override
	public void onReturnDeviceInfo(
			Hashtable<String, String> stringStringHashtable) {
		HPLog.i(TAG, "onReturnDeviceInfo:");
	}

	@Override
	public void onReturnTransactionResult(
			EmvSwipeController.TransactionResult transactionResult) {
		HPLog.i(TAG, "onReturnTransactionResult:" + transactionResult);
	}

	/*
	 * BbposVoiceSwiper:onWaitingForCard: BbposVoiceSwiper:onRequestSetAmount:
	 * BbposVoiceSwiper:onRequestDisplayText:INSERT_CARD
	 * BbposVoiceSwiper:onRequestDisplayText:PLEASE_WAIT
	 * BbposVoiceSwiper:onRequestDisplayText:TRANSACTION_TERMINATED
	 * BbposVoiceSwiper:onRequestDisplayText:PLEASE_WAIT
	 * BbposVoiceSwiper:onRequestDisplayText:REMOVE_CARD
	 * BbposVoiceSwiper:onReturnBatchData:**************
	 * BbposVoiceSwiper:onReturnTransactionResult:CARD_BLOCKED
	 */
	@Override
	public void onReturnTransactionResult(
			EmvSwipeController.TransactionResult transactionResult,
			Hashtable<String, String> stringStringHashtable) {
		HPLog.i(TAG, "onReturnTransactionResult:" + transactionResult);
		if (EmvSwipeController.TransactionResult.APPROVED == transactionResult) {

		} else {
			// swipe card failed
			// ！！！不管emv结果。我们只要拿到dcData可以做交易，就当成功了！！！
			// mData = null;
		}
		mLock.unlock(AsynSwiperLock.OLD_INPUT_PWD);
	}

	@Override
	public void onReturnBatchData(String s) {
		HPLog.i(TAG, "onReturnBatchData:" + s);
	}

	@Override
	public void onReturnTransactionLog(String s) {
		HPLog.i(TAG, "onReturnTransactionLog:" + s);
	}

	@Override
	public void onReturnReversalData(String s) {
		HPLog.i(TAG, "onReturnReversalData:" + s);
	}

	@Override
	public void onReturnPowerOnIccResult(boolean b, String s, String s2, int i) {
		HPLog.i(TAG, "onReturnPowerOnIccResult:" + b + " " + s + " " + s2 + " "
				+ i);
	}

	@Override
	public void onReturnPowerOffIccResult(boolean b) {
		HPLog.i(TAG, "onReturnPowerOffIccResult: " + b);
	}

	@Override
	public void onReturnApduResult(boolean b, String s, int i) {
		HPLog.i(TAG, "onReturnApduResult:" + b + " " + s + " " + i);
	}

	@Override
	public void onReturnApduResultWithPkcs7Padding(boolean b, String s) {
		HPLog.i(TAG, "onReturnApduResultWithPkcs7Padding:");
	}

	@Override
	public void onReturnViposExchangeApduResult(String s) {
		HPLog.i(TAG, "onReturnViposExchangeApduResult:" + s);
		++mSwipeTransData.mBbposICTranIndex;
		if (mSwipeTransData.mBbposICTranIndex < apdus.length) {
			mEmvSwipeController
					.viposExchangeApdu(apdus[mSwipeTransData.mBbposICTranIndex]);
		} else {
			mEmvSwipeController.sendOnlineProcessResult("8A023030");
		}
	}

	@Override
	public void onReturnViposBatchExchangeApduResult(
			Hashtable<Integer, String> data) {
		HPLog.i(TAG, "onReturnViposBatchExchangeApduResult:");
		// 单独加密数据的返回结果
		if (null != data.get(SINGLE_ENC_DATA_KEY)) {
			HPLog.i(TAG, "enc data result:" + data.get(SINGLE_ENC_DATA_KEY));
			mData = data.get(SINGLE_ENC_DATA_KEY)
					.substring(0, data.get(SINGLE_ENC_DATA_KEY).length() - 4)
					.toUpperCase(Locale.US);
			mLock.unlock(AsynSwiperLock.CACL_DATA);
		} else if (null != data.get(SINGLE_ENC_MAC_KEY)) {
			// 单独做mac的数据返回
			HPLog.i(TAG,
					"onBatchApduResponseReceived--------------"
							+ data.get(SINGLE_ENC_MAC_KEY));
			mData = data.get(SINGLE_ENC_MAC_KEY);
			mLock.unlock(AsynSwiperLock.CACL_MAC);
		} else {

		}
	}

	@Override
	public void onReturnEmvCardDataResult(boolean b, String s) {
		HPLog.i(TAG, "onReturnEmvCardDataResult:" + b + " " + s);
	}

	@Override
	public void onReturnEmvCardNumber(String s) {
		HPLog.i(TAG, "onReturnEmvCardNumber:" + s);
		mData = s;
		mLock.unlock(AsynSwiperLock.OLD_SWIPE_CARD);
	}

	@Override
	public void onReturnPowerOnNfcResult(boolean b, String s, int i) {
		HPLog.i(TAG, "onReturnPowerOnNfcResult:");
	}

	@Override
	public void onReturnPowerOffNfcResult(boolean b) {
		HPLog.i(TAG, "onReturnPowerOffNfcResult:");
	}

	@Override
	public void onReturnNfcDataResult(
			EmvSwipeController.NfcDataExchangeStatus nfcDataExchangeStatus,
			String s, int i) {
		HPLog.i(TAG, "onReturnNfcDataResult:");
	}

	@Override
	public void onReturnKsn(Hashtable<String, String> stringStringHashtable) {
		HPLog.i(TAG, "onReturnKsn:");
		String csn = stringStringHashtable.get("csn");
		mData = csn;
		mLock.unlock(AsynSwiperLock.GETCSN);
	}

	@Override
	public void onReturnUpdateTerminalSettingResult(
			EmvSwipeController.TerminalSettingStatus terminalSettingStatus) {
		HPLog.i(TAG, "onReturnUpdateTerminalSettingResult:"
				+ terminalSettingStatus);
	}

	@Override
	public void onReturnReadTerminalSettingResult(
			EmvSwipeController.TerminalSettingStatus terminalSettingStatus,
			String s) {
		HPLog.i(TAG, "onReturnReadTerminalSettingResult:"
				+ terminalSettingStatus);
	}

	/*
	 * @Override public void onReturnAutoConfigProgress(double v) { HPLog.i(TAG,
	 * "onReturnReadTerminalSettingResult:" + v); }
	 * 
	 * @Override public void onReturnAutoConfigResult(boolean b, String s) {
	 * HPLog.i(TAG, "onReturnAutoConfigResult:" + b + " " + s); }
	 * 
	 * @Override public void onReturnSetConfigResult(boolean b) { HPLog.i(TAG,
	 * "onReturnSetConfigResult:" + b); }
	 */
	private static int findIndex(ArrayList<String> strings, String cardType) {
		int index;
		// 查找出第一的位置
		for (index = 0; index < strings.size(); index++) {
			if (cardType.equals(strings.get(index))) {
				break;
			}
		}
		return index;
	}

	@Override
	public void onRequestSelectApplication(final ArrayList<String> strings) {
		HPLog.i(TAG, "onRequestSelectApplication:");
		String applicationType = mSwipeTransData.mICSelectedApplication;
		if (!TextUtils.isEmpty(applicationType)) {
			// 一次交易中，如果用户已经选择了卡类型，直接选择
			int index = strings.indexOf(applicationType);
			HPLog.i(TAG, "user already select " + applicationType
					+ " and index is " + index);
			if (-1 != index) {
				mEmvSwipeController.selectApplication(index);
			} else {
				mEmvSwipeController.cancelSelectApplication();
				HPLog.e(TAG, "error!");
			}
			return;
		}
		/**
		 * list 和 arrayList对应。
		 */
		final ArrayList<String> list = new ArrayList<String>(2);
		ArrayList<String> listName = new ArrayList<String>(2);
		for (int i = 0; i < strings.size(); i++) {
			String cardType = strings.get(i);
			// 超级转账的限制，放到具体业务里，不要放在刷卡器里
			if (cardType.contains("CREDIT")/*
											 * && mSwiperMode !=
											 * SwiperMode.SUPER_TRANS
											 */) {
				listName.add(mContext.getString(R.string.card_credit));
				list.add(cardType);
			} else if (cardType.contains("DEBIT")) {
				listName.add(mContext.getString(R.string.card_debit));
				list.add(cardType);
			}
		}
		if (0 == list.size()) {
			HPLog.e(TAG, "No available application to select. cancel it");
			mSelectApplication.showNoAvailableApp(new Runnable() {
				@Override
				public void run() {
					if (null != mEmvSwipeController) {
						mEmvSwipeController.cancelSelectApplication();
					}
				}
			});
			return;
		}
		// prompt to select cardType
		final IICSelectApplicationCallback selectApplicationCallback = new IICSelectApplicationCallback() {
			@Override
			public void onCardTypeSelect(int index) {
				HPLog.i(TAG, "list size:" + list.size() + " and user select "
						+ index);
				if (null != mEmvSwipeController && -1 != index
						&& index < list.size()) {
					int realIndex = findIndex(strings, list.get(index));
					if (-1 != realIndex && realIndex < strings.size()) {
						// 记录用户选择的ApplicationType
						mSwipeTransData.mICSelectedApplication = list
								.get(index);
						mEmvSwipeController.selectApplication(index);
					} else {
						HPLog.e(TAG, "cannot find this select: " + realIndex
								+ ", so cancel it!");
						mEmvSwipeController.cancelSelectApplication();
					}
				} else {
					HPLog.e(TAG, "cancel select Application");
					mEmvSwipeController.cancelSelectApplication();
				}
			}
		};
		mSelectApplication.showSelectICApp(listName, selectApplicationCallback);
		// if (list.size() < 2 || null == mSelectApplication) {
		// int index = findIndex(strings, list.get(0));
		// HPLog.i(TAG,
		// "select Application null or only one select. default select 0");
		// mEmvSwipeController.selectApplication(index);
		// } else {
		//
		// }
	}

	@Override
	public void onRequestSetAmount() {
		HPLog.i(TAG, "onRequestSetAmount:");
		// 这个里面的值都是没有意义的。和我们业务无关。
		mEmvSwipeController.setAmount("1", "", "156",
				EmvSwipeController.TransactionType.GOODS);
	}

	@Override
	public void onRequestPinEntry() {
		HPLog.i(TAG, "onRequestPinEntry:");
		// 发送无意义的密码。真正的密码加密，后面再做。
		mEmvSwipeController.sendPinEntryResult("111111");
	}

	@Override
	public void onRequestVerifyID(String s) {
		HPLog.i(TAG, "onRequestVerifyID:");
	}

	@Override
	public void onRequestCheckServerConnectivity() {
		HPLog.i(TAG, "onRequestCheckServerConnectivity:");
	}

	@Override
	public void onRequestOnlineProcess(String s) {
		HPLog.i(TAG, "onRequestOnlineProcess:" + s);
		mData = s;
		// 这里用于发送第一个。
		mEmvSwipeController.viposExchangeApdu(apdus[0]);
		// mLock.unlock(AsynSwiperLock.OLD_INPUT_PWD);
	}

	@Override
	public void onRequestTerminalTime() {
		HPLog.i(TAG, "onRequestTerminalTime:");
		String time = new SimpleDateFormat("yyMMddHHmmss").format(Calendar
				.getInstance().getTime());
		mEmvSwipeController.sendTerminalTime(time);
	}

	@Override
	public void onRequestDisplayText(EmvSwipeController.DisplayText displayText) {
		HPLog.i(TAG, "onRequestDisplayText:" + displayText);
	}

	@Override
	public void onRequestClearDisplay() {
		HPLog.i(TAG, "onRequestClearDisplay:");
	}

	@Override
	public void onRequestReferProcess(String s) {
		HPLog.i(TAG, "onRequestReferProcess:" + s);
	}

	@Override
	public void onRequestAdviceProcess(String s) {
		HPLog.i(TAG, "onRequestAdviceProcess:" + s);
	}

	@Override
	public void onRequestFinalConfirm() {
		HPLog.i(TAG, "onRequestFinalConfirm:");
		mEmvSwipeController.sendFinalConfirmResult(true);
	}

	@Override
	public void onAutoConfigProgressUpdate(double v) {
		HPLog.i(TAG, "onAutoConfigProgressUpdate:" + v);
	}

	@Override
	public void onAutoConfigCompleted(boolean b, String s) {
		HPLog.i(TAG, "onAutoConfigCompleted:" + b + ":" + s);
	}

	@Override
	public void onAutoConfigError(
			EmvSwipeController.AutoConfigError autoConfigError) {
		HPLog.i(TAG, "onAutoConfigError:" + autoConfigError);
	}

	@Override
	public void onBatteryLow(EmvSwipeController.BatteryStatus batteryStatus) {
		HPLog.i(TAG, "onBatteryLow:" + batteryStatus);
		if (null != mSelectApplication
				&& mSelectApplication instanceof SwiperCallback) {
			((SwiperCallback) mSelectApplication).onBatteryLow();
		}
	}

	@Override
	public void onNoDeviceDetected() {
		HPLog.i(TAG, "onNoDeviceDetected:");
	}

	@Override
	public void onDevicePlugged() {
		HPLog.i(TAG, "onDevicePlugged:");
	}

	@Override
	public void onDeviceUnplugged() {
		HPLog.i(TAG, "onDeviceUnplugged:");
		mLock.unlock(AsynSwiperLock.IDLE);
	}

	@Override
	public void onDeviceHere(boolean b) {
		HPLog.i(TAG, "onDeviceHere:");
	}

	@Override
	public void onError(EmvSwipeController.Error error) {
		HPLog.i(TAG, "onError:" + error);
		mLock.unlock(AsynSwiperLock.IDLE);
	}

	@Override
	public void onPowerDown() {
		HPLog.i(TAG, "onPowerDown:");
	}

	@Override
	protected boolean prepareAdditionalData() {
		boolean result = super.prepareAdditionalData();
		if (mSwipeTransData.isIcTrans) {
			HPLog.i(TAG, "ic trans. startEmv to get DCData");
			if (iccStartEmv().mStatus != SwipeStatus.SWIPE_OK) {
				return false;
			}
		}
		return result;
	}
}
